home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2007 December
/
PCWKCD1207B.iso
/
Blogowanie poza sfera
/
Flock 1.0 beta
/
flock-1.0RC3.en-US.win32.exe
/
flock
/
components
/
flockFavoritesService.js
< prev
next >
Wrap
Text File
|
2007-10-18
|
58KB
|
1,764 lines
// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2007
// http://flock.com
//
// This file may be used under the terms of of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL
// XPConnect Helpers
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
// Constants
const FAVORITES_RDF_FILE = "flock-data.rdf";
const OLD_FAVORITES_RDF_FILE = "flock_favorites.rdf";
const OLD_FAVORITES_RDF_FILE_RELIC = "flock_favorites_old.rdf";
const FAVORITES_CID = Components.ID("{3606f63a-f874-42fa-8174-cc9a0dd0a712}");
// Contract IDs
const FAVORITES_CONTRACTID = "@flock.com/favorites-service;1";
const CONTAINER_CONTRACTID = "@mozilla.org/rdf/container;1";
const DIRECTORY_SVC_CONTRACTID = "@mozilla.org/file/directory_service;1";
const LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
// Service handles
const RDFS = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
const RDFCU = Cc["@mozilla.org/rdf/container-utils;1"].getService(Ci.nsIRDFContainerUtils);
const PREFS = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
const IOS = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
// Namespaces Helpers
function Namespace(ns) { return function (arg) { return RDFS.GetResource(ns+arg); } }
const W3RDF = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
const NSRDF = Namespace("http://home.netscape.com/NC-rdf#");
const WBRDF = Namespace("http://home.netscape.com/WEB-rdf#");
const FLRDF = Namespace("http://flock.com/rdf#");
const COLRDF = Namespace("urn:flock:collection:");
// RDF Properties
const RDF_URL = NSRDF("URL");
const RDF_TAGS = FLRDF("tags");
const RDF_TAG = FLRDF("tag");
const RDF_WSID = FLRDF("wsid");
const RDF_NAME = NSRDF("Name");
const RDF_PERMISSIONS = FLRDF("permissions");
const RDF_TYPE = W3RDF("type");
const RDF_FAVORITE = FLRDF("Favorite");
const RDF_COLLECTION = FLRDF("Collection");
const RDF_FOLDER = FLRDF("Folder");
const RDF_LIVEMARK = NSRDF("Livemark");
const RDF_FEEDURL = NSRDF("FeedURL");
const RDF_FEEDENABLED = FLRDF("feedEnabled");
const RDF_SHORTCUTURL = NSRDF("ShortcutURL");
const RDF_DESCRIPTION = NSRDF("Description");
const RDF_NSYNC = FLRDF("nsync");
const RDF_LOCAL = FLRDF("local");
const RDF_LASTMODIFIEDDATE = WBRDF("LastModifiedDate");
const RDF_LASTVISITDATE = WBRDF("LastVisitDate");
const RDF_ADDEDDATE = FLRDF("FavoriteAddDate");
const RDF_FAVORITESROOT = FLRDF("BookmarksRoot");
const RDF_COLLECTIONSROOT = FLRDF("CollectionsRoot");
const RDF_FOLDERSROOT = FLRDF("FoldersRoot");
const RDF_TAGSROOT = FLRDF("TagsRoot");
const RDF_INSTANCEOF = W3RDF("instanceOf");
const RDF_SEQ = W3RDF("Seq");
const RDF_FEED = FLRDF("feed");
const RDF_TOOLBAR = FLRDF("toolbar");
const RDF_STORE = FLRDF("store");
const RDF_VERSION = FLRDF("version");
const RDF_HASFEEDS = FLRDF("hasFeeds");
const RDF_ISFEED = FLRDF("isFeed");
const RDF_COOPTYPE = FLRDF("CoopType");
// RDF Helpers
var rdfLiteral = RDFS.GetLiteral;
var rdfDate = RDFS.GetDateLiteral;
var rdfInt = RDFS.GetIntLiteral;
function rdfBoolean(b) { return rdfLiteral(b ? "true" : "false"); }
const RDF_TRUE = rdfBoolean(true);
const RDF_FALSE = rdfBoolean(false);
// Prefs
const PREF_INDEXED_INITIAL_FAVORITES = "flock.favorites.indexedInitialFavorites";
const PREF_FIRSTRUN_COMPLETED = "flock.firstrun.components.browser_startup.completed";
const PREF_MYWORLD_TOPSITES_COUNT = "flock.myworld.topsites.count";
const PREF_MYWORLD_TOPSITES_COUNT_DEFAULT = 25;
const RECOUNT_INTERVAL = 500; // half-second delay in propagating count changes
const SYNC_TIMEOUT = 250; // wait 250 ms for the RDF node to fully populate
// Cardinal migration
const CARDINAL_BM_TOOLBAR_DEFAULT_NAME = "Favorites Toolbar";
function getObserverService() {
return Cc['@mozilla.org/observer-service;1']
.getService(Ci.nsIObserverService);
}
// Remove Top Site
function removeSite(aFolderURN, oldFav, aCoopDS) {
if (!oldFav) return;
var c_Folder = aCoopDS.get(aFolderURN);
c_Folder.children.remove(oldFav);
}
// Bubble Sorting Routine
function bubbleSort(aFolderURN, newFav, aCompareFunction, aCoopDS)
{
var bInserted = false;
var c_Folder = aCoopDS.get(aFolderURN);
// Get Children of c_Folder
var childEnum = c_Folder.children.enumerate();
var aTopSiteCount = 0;
var bAlreadySeen = false;
var iMaxCount = PREF_MYWORLD_TOPSITES_COUNT_DEFAULT;
if (PREFS.getPrefType(PREF_MYWORLD_TOPSITES_COUNT)) {
iMaxCount = PREFS.getIntPref(PREF_MYWORLD_TOPSITES_COUNT);
} else {
PREFS.setIntPref(PREF_MYWORLD_TOPSITES_COUNT, iMaxCount);
}
while (childEnum.hasMoreElements()) {
aTopSiteCount++;
var child = childEnum.getNext();
// If we have NOT inserted, and this child is the same as what we want to insert
// BAIL out.
if (!bInserted && checkDupe(aFolderURN, newFav, child)) {
return;
}
// If we have NOT inserted yet, check for an appropriate spot
if (!bInserted && (aCompareFunction(newFav,child) >= 0)) {
var aIndex = c_Folder.children.indexOf(child);
while(c_Folder.children.has(newFav)) {
c_Folder.children.remove(newFav);
}
c_Folder.children.insertAt(newFav,aIndex);
bInserted = true;
break;
}
}
// Never inserted
// no items were in the collection before OR it is the oldest item.
// Insert only if there's room
if (!bInserted && (aTopSiteCount+1 <= iMaxCount)) {
c_Folder.children.insertAt(newFav,aTopSiteCount+1);
}
// Go through the list again and make sure we remove the max elements
var e = c_Folder.children.enumerate();
var iIndex = 0;
while(e.hasMoreElements()) {
var maxchild = e.getNext();
iIndex++;
// We're over our allotted amount.. remove!
if (iIndex > iMaxCount && maxchild) {
c_Folder.children.remove(maxchild);
}
}
}
function checkDupe(aFolderURN, newFav, child) {
switch(aFolderURN) {
case "urn:flock:topsites": {
if(newFav.URL == child.URL)
return true;
} break;
case "urn:flock:topfeeds": {
if(newFav.URL == child.URL)
return true;
} break;
case "urn:flock:topmedia": {
if(newFav.name == child.name
&& newFav.service == child.service) {
return true;
}
}
}
return false;
}
// This data structure contains all the information we need to determine and
// maintain the list of "top" faves in each of the supported categories (Sites,
// Feeds, Media). The associative array keys are URNs of the folder nodes.
// 'criteria' - array of predicate-object pairs used to identify the type
// 'triggers' - array of type-source-predicate-object tuples (arc property
// operations) that will trigger the observer
// 'observer' - callback for triggers, refreshes folder contents
// 'compare' - function used to sort items of that type
var gTopFaves = [
{
urn: "urn:flock:topsites",
criteria: [[FLRDF("flockType"), rdfLiteral("bookmark")]],
triggers: [[Ci.flockIRDFObserver.WATCH_TYPES, null, WBRDF("LastModifiedDate"), null],
[Ci.flockIRDFObserver.TYPE_ALL, null, WBRDF("LastVisitDate"), null]
],
observer: {
rdfChanged: function (aDS, aType, aSource, aPredicate, aTarget, aOldTarget) {
if (!aSource) return;
var fav = this.svc.faves_coop.get_from_resource(aSource);
if (aType == Ci.flockIRDFObserver.TYPE_UNASSERT) {
// Remove this from topsites
removeSite(this.ft.urn, fav, this.svc.faves_coop);
} else {
bubbleSort(this.ft.urn, fav, this.ft.compare, this.svc.faves_coop);
}
var obs = getObserverService();
obs.notifyObservers(null, 'refresh-myworld-topsites', false);
}
},
compare: function (aResourceA, aResourceB) {
// Compare the two resource's timestamp
// -1 = A older than B
// 0 = equivalent
// 1 = A newer than B
return aResourceA.LastVisitDate - aResourceB.LastVisitDate;
},
initialize: function (ft,svc,coopObj)
{
if (coopObj == null) {
coopObj = Cc["@flock.com/singleton;1"]
.getService(Ci.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject
.bookmarks_root;
}
var e = coopObj.children.enumerate();
while (e.hasMoreElements()){
var entry = e.getNext();
if (entry.flockType == "bookmark") {
bubbleSort(ft.urn, entry, ft.compare, svc.faves_coop);
} else if (entry.flockType == "folder") {
this.initialize(ft,svc,entry);
}
}
}
},
{
urn: "urn:flock:topfeeds",
criteria: [[FLRDF("flockType"), rdfLiteral("feed")]],
triggers: [[Ci.flockIRDFObserver.TYPE_ALL, null, FLRDF("datevalue"), null],
[Ci.flockIRDFObserver.TYPE_ALL, null, FLRDF("unseenItems"), null]
],
observer: {
rdfChanged: function (aDS, aType, aSource, aPredicate, aTarget, aOldTarget) {
if (!aSource) return;
var id = aSource.ValueUTF8;
var sync = { // Check if it's a feed
notify: function syncTopFeeds(timer) {
if (timer) {
delete this.svc.syncTimers[id];
}
if (!checkCriteria(this.ft.criteria,aSource,this.svc.dataSource)) {
return;
}
// Check parent for feed subscription
var c_Feed = this.svc.faves_coop.get_from_resource(aSource);
var parents = c_Feed.getParents();
for each (var parent in parents) {
var node = parent;
while (!node.isInstanceOf(this.svc.faves_coop.FeedContext)) {
var nodeParents = node.getParents();
if (nodeParents.length)
node = nodeParents[0];
else
break;
}
if (node.id() == "urn:flock:feedcontext:news") {
bubbleSort(this.ft.urn, c_Feed, this.ft.compare, this.svc.faves_coop);
break;
}
}
}
}
sync.ft = this.ft;
sync.svc = this.svc;
if (this.svc.syncTimers[id]) {
this.svc.syncTimers[id].cancel();
}
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(sync, SYNC_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
this.svc.syncTimers[id] = timer;
}
},
compare: function (aResourceA, aResourceB) {
// A == newFav
return aResourceA.datevalue - aResourceB.datevalue;
},
initialize: function (ft,svc,coopObj)
{
if(coopObj == null) {
coopObj = Cc["@flock.com/singleton;1"]
.getService(Ci.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject
.get("urn:flock:feedcontext:news");
}
// If we are still null, forget it
if(coopObj == null)
return;
var e = coopObj.children.enumerate();
while (e.hasMoreElements()){
var entry = e.getNext();
if(entry.flockType == "feed"){
bubbleSort(ft.urn, entry, ft.compare, svc.faves_coop);
} else if (entry.flockType == "folder") {
this.initialize(ft,svc,entry);
}
}
}
},
{
urn: "urn:flock:topmedia",
criteria: [[W3RDF("type"), NSRDF("MediaQuery")]],
triggers: [[Ci.flockIRDFObserver.TYPE_ALL, null, FLRDF("latestDate"), null]],
observer: {
rdfChanged: function (aDS, aType, aSource, aPredicate, aTarget, aOldTarget) {
if (!aSource) return;
if(aType == Ci.flockIRDFObserver.TYPE_UNASSERT) {
// Don't process
return;
}
var id = aSource.ValueUTF8;
var sync = { // Check if it's a media obj
notify: function syncTopMedia(timer) {
if (timer) {
delete this.svc.syncTimers[id];
}
if (!checkCriteria(this.ft.criteria,aSource,this.svc.dataSource)) {
return;
}
// Check parent for media subscription
var c_Media = this.svc.faves_coop.get_from_resource(aSource);
var parents = c_Media.getParents();
for (var i in parents) {
var parent = parents[i];
if (parent.id() == "urn:media:favorites") {
bubbleSort(this.ft.urn, c_Media, this.ft.compare, this.svc.faves_coop);
break;
}
}
}
}
sync.ft = this.ft;
sync.svc = this.svc;
if (this.svc.syncTimers[id]) {
this.svc.syncTimers[id].cancel();
}
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(sync, SYNC_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
this.svc.syncTimers[id] = timer;
}
},
compare: function (aResourceA, aResourceB) {
// A == newFav
return aResourceA.latestDate - aResourceB.latestDate;
},
initialize: function (ft,svc,coopObj)
{
if(coopObj == null) {
coopObj = Cc["@flock.com/singleton;1"]
.getService(Ci.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject
.get("urn:media:favorites");
}
// If we are still null, forget it
if(coopObj == null)
return;
var e = coopObj.children.enumerate();
while (e.hasMoreElements()){
var entry = e.getNext();
// JMC - MediaQuery is no longer CountedObject
if(entry.flockType == "media"){
bubbleSort(ft.urn, entry, ft.compare, svc.faves_coop);
} else if (entry.flockType == "folder") {
this.initialize(ft,svc,entry);
}
}
}
}
];
// checks incoming criteria for a match
function checkCriteria(aCriteriaArr,aSource,aDataSource)
{
aSource.QueryInterface(Components.interfaces.nsIRDFResource);
for (var i=0;i<aCriteriaArr.length;i++) {
var prop = aCriteriaArr[i][0].QueryInterface(Ci.nsIRDFResource);
var value = aCriteriaArr[i][1].QueryInterface(Ci.nsIRDFNode);
if(!aDataSource.HasAssertion(aSource, prop, value, true)) {
return false;
}
}
return true;
}
// Component Utils (just used for the timer/scheduler)
var gCompTK;
function getCompTK() {
if (!gCompTK) {
var gCompTK = Cc["@flock.com/singleton;1"]
.getService(Ci.flockISingleton)
.getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
.wrappedJSObject;
}
return gCompTK;
}
function loadSubScript(spec)
{
var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
var context = {};
loader.loadSubScript(spec, context);
return context;
}
// nsISimpleEnumerator implementation
function simpleEnumerator(aArray)
{
aArray.hasMoreElements = function () {
return this.length != 0;
}
aArray.getNext = function () {
return this.shift();
}
return aArray;
}
function makeNSIArray(aArray) {
aArray.queryElementAt = function (aIndex, aIIDRef) {
return aArray[aIndex].QueryInterface(aIIDRef);
}
aArray.enumerate = function () { return simpleEnumerator(this); }
aArray._indexOf = aArray.indexOf;
aArray.indexOf = function (aStartIndex, aElement) { return this._indexOf(aElement, aStartIndex); }
return aArray;
}
function getProfDirFile()
{
var dirService = Cc[DIRECTORY_SVC_CONTRACTID].getService(Ci.nsIProperties);
// create a datasource in the profile directory
var profd = dirService.get("ProfD", Ci.nsIFile);
var file = Cc[LOCAL_FILE_CONTRACTID].createInstance(Ci.nsILocalFile);
file.initWithPath(profd.path);
return file;
}
function base64Encode(aInput) {
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
while (aInput.length > 0) {
output += chars[aInput.charCodeAt(0) >> 2];
output += chars[((aInput.charCodeAt(0) & 0x03) << 4) |
(aInput.length > 1 ? ((aInput.charCodeAt(1) & 0xF0) >> 4) : 0)];
output += chars[aInput.length > 1 ?
((aInput.charCodeAt(1) & 0x0F) << 2) |
(aInput.length > 2 ? ((aInput.charCodeAt(2) & 0xC0) >> 6) : 0) : 64];
output += chars[aInput.length > 2 ?
(aInput.charCodeAt(2) & 0x3F) : 64];
if (aInput.length > 3) {
aInput = aInput.substr(3);
} else {
break;
}
}
return output;
}
// ======================================================
// ========== BEGIN favoritesService Component ==========
// ======================================================
// BEGIN Constructor
function favoritesService()
{
this._logger = Cc["@flock.com/logger;1"].createInstance(Ci.flockILogger);
this._logger.init("favoritesService");
this._logger.info("Created Favorites Service Object");
// JMC - Delay init until the DIRService Exists
this.loaded = false;
}
// END Constructor
// BEGIN nsISupports
favoritesService.prototype.QueryInterface =
function (aIID)
{
if ( !aIID.equals(Ci.nsIBookmarksService) &&
!aIID.equals(Ci.flockIFavoritesService) &&
!aIID.equals(Ci.flockIFeedContextObserver) &&
!aIID.equals(Ci.flockIMigratable) &&
!aIID.equals(Ci.nsICharsetResolver) &&
!aIID.equals(Ci.nsIClassInfo) &&
!aIID.equals(Ci.nsIObserver) &&
!aIID.equals(Ci.nsISupports) )
{
throw Cr.NS_ERROR_NO_INTERFACE;
}
return this;
}
// END nsISupports
// BEGIN nsIClassInfo
favoritesService.prototype.flags = Ci.nsIClassInfo.SINGLETON;
favoritesService.prototype.classDescription = "Flock Favorites Service";
favoritesService.prototype.getInterfaces = function (count) {
var interfaceList = [ Ci.nsIBookmarksService, Ci.flockIFavoritesService,
Ci.nsICharsetResolver,
Ci.flockIMigratable, Ci.nsIClassInfo ];
count.value = interfaceList.length;
return interfaceList;
}
favoritesService.prototype.getHelperForLanguage = function (count) { return null; }
// END nsIClassInfo
// BEGIN nsIObserver
favoritesService.prototype.observe =
function favoritesService_observe(subject, topic, data)
{
if ( topic == "nsPref:changed" &&
data == PREF_FIRSTRUN_COMPLETED &&
PREFS.getBoolPref(PREF_FIRSTRUN_COMPLETED) )
{
for (var folderURN in gTopFaves) {
var faveType = gTopFaves[folderURN];
// start gTopFaves init function
faveType.initialize(faveType,this,null);
}
if (!PREFS.getBoolPref(PREF_INDEXED_INITIAL_FAVORITES)) {
var index_initial_callback = {};
index_initial_callback.svc = this;
index_initial_callback.notify = function (timer) {
var e = this.svc.getAllFavorites();
while (e.hasMoreElements()) {
var u = e.getNext().QueryInterface(Ci.nsIRDFResource).ValueUTF8;
//this.svc.luceneIndexer.AddDocument(u);
}
PREFS.setBoolPref(PREF_INDEXED_INITIAL_FAVORITES, true);
}
}
}
if (topic == "flock-shutdown") {
this.obs.removeObserver(this, "flock-shutdown");
this._shutdown();
}
}
// END nsIObserver
// BEGIN flockIFeedContextObserver
favoritesService.prototype.onSubscribe = function(context, feed)
{
function compare(a, b) {
return a.datevalue - b.datevalue;
}
var id = this.faves_coop.Feed.get_id({ URL: feed.getURL().spec });
var obj = this.faves_coop.get(id);
bubbleSort("urn:flock:topfeeds", obj, compare, this.faves_coop);
}
favoritesService.prototype.onUnsubscribe = function(context, feed)
{
var id = this.faves_coop.Feed.get_id({ URL: feed.getURL().spec });
var obj = this.faves_coop.get(id);
removeSite("urn:flock:topfeeds", obj, this.faves_coop);
}
favoritesService.prototype.onUnreadCountChange = function(context, unreadCount)
{
}
// END flockIFeedContextObserver
// BEGIN flockIFavoritesService
favoritesService.prototype.setupDefaultFavorites = function ()
{
this._logger.info("SetupDefaultFavorites");
var faves_coop = this.faves_coop;
var favSrv = this;
var context = {coop: faves_coop, service: favSrv, dump: dump};
var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://flock/locale/favorites/defaultFavorites.js", context);
// Load up the defaul media favs too.
loader.loadSubScript("chrome://flock/locale/photo/defaultMedia.js", context);
}
favoritesService.prototype.init =
function favoritesService_init(aDataSource)
{
if (this.loaded) return;
aDataSource.QueryInterface(Ci.flockIRDFObservable);
this.dataSource = aDataSource;
this.faves_coop = Cc["@flock.com/singleton;1"]
.getService(Ci.flockISingleton)
.getSingleton("chrome://flock/content/common/load-faves-coop.js")
.wrappedJSObject;
this.syncTimers = {};
var prefsService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
var favesBranch = prefsService.getBranch("flock.favorites.");
// Convert 0.9.0.x LastVisitDate/LastModifiedDate from strings to real dates
var migratedStringDates;
try {
migratedStringDates = favesBranch.getBoolPref("migratedStringDates");
} catch (ex) {
migratedStringDates = false;
}
if (!migratedStringDates) {
var inst = this;
function convertOldDate(aResource, aProp) {
var target = inst.dataSource.GetTarget(aResource, aProp, true);
if (target && target instanceof Ci.nsIRDFLiteral) {
var dateStr = target.QueryInterface(Ci.nsIRDFLiteral).Value;
var time = Date.parse(dateStr);
if (!isNaN(time)) {
inst.dataSource.Change(aResource, aProp, target,
RDFS.GetDateLiteral(1000 * time));
} else {
inst.dataSource.Unassert(aResource, aProp, target);
}
}
}
var resources = this.faves_coop.Bookmark.all_ids();
while (resources.hasMoreElements()) {
var resource = resources.getNext();
convertOldDate(resource, RDF_LASTVISITDATE);
convertOldDate(resource, RDF_LASTMODIFIEDDATE);
}
favesBranch.setBoolPref("migratedStringDates", true);
}
// Make sure no favorite has more than one parent (only once)
var uniqueId = false;
try {
uniqueId = favesBranch.getBoolPref("uniqueid");
} catch(e) { /* The pref is not set yet */ }
if (!uniqueId) {
for (var i in gTopFaves) {
// Change the top favorites from the Folder type to TopFavesFolder
try {
var res = RDFS.GetResource(gTopFaves[i].urn);
var oldtype = this.dataSource.GetTarget(res, W3RDF("type"), true);
var oldcooptype = this.dataSource.GetTarget(res, FLRDF("CoopType"), true);
if (oldtype)
this.dataSource.Change(res, W3RDF("type"), oldtype, FLRDF("TopFavesFolder"));
if (oldcooptype)
this.dataSource.Change(res, FLRDF("CoopType"), oldcooptype, FLRDF("TopFavesFolder"));
}
catch (e) {}
}
var allFaves = this.faves_coop.Bookmark.all();
var nonUnique = [];
while (allFaves.hasMoreElements()) {
var fave = allFaves.getNext();
// Assuming all bookmarks with an id starting with "urn:" are online
// faves, and thus should not be transformed.
var urn = fave.id();
if (urn.substr(0, 4) == "urn:") {
continue;
}
var parentCount = 0;
for each (var parent in fave.getParents()) {
if (parent instanceof this.faves_coop.Folder)
parentCount++;
}
if (parentCount > 1) {
nonUnique.push(fave);
}
}
for each (var fave in nonUnique) {
// This favorite has more than one parent.
// We need to clone it so each favorite has only one parent.
var firstparent = true;
var faveRes = RDFS.GetResource(fave.id());
for each (var parent in fave.getParents()) {
if (parent instanceof this.faves_coop.Folder) {
if (firstparent) {
// The first parent keeps the original favorite
firstparent = false;
}
else {
// Other parents get a clone
var newRes = this.cloneResource(faveRes);
var newFave = this.faves_coop.get(newRes.Value);
var position = parent.children.indexOf(fave);
parent.children.insertAt(newFave, position);
parent.children.remove(fave);
}
}
else {
// MyWorld's "Top Faves" keeps the original
}
}
}
favesBranch.setBoolPref ("uniqueid", true);
}
this._obsObsrv = {};
this._obsObsrv.observe = function main_observer(aSubject, aTopic, aVerb) {
if( aTopic == "myworld-enableDisable-observers" ) {
if( aVerb == "true" ) {
// Re-enable the arc observers
for (var folderURN in this.gtf) {
// Make sure the sorting folders exist for each type
var faveType = this.gtf[folderURN];
faveType.observer.ft = faveType;
faveType.observer.svc = this.svc;
faveType.root = this.fc.get(faveType.urn);
if (!faveType.root) { faveType.root = new this.fc.TopFavesFolder(faveType.urn); }
// Start watching for the appropriate arc changes
for (var t in faveType.triggers) {
var trig = faveType.triggers[t];
this.ds.addArcObserver(trig[0], trig[1], trig[2], trig[3], faveType.observer);
}
}
var feedManager = Cc["@flock.com/feed-manager;1"].getService(Ci.flockIFeedManager);
var newsFeedContext = feedManager.getFeedContext("news");
newsFeedContext.addObserver(this.svc);
} else {
// remove the arc observers
for (var folderURN in this.gtf) {
// Make sure the sorting folders exist for each type
var faveType = this.gtf[folderURN];
faveType.observer.ft = faveType;
faveType.observer.svc = this.svc;
faveType.root = this.fc.get(faveType.urn);
if (!faveType.root) { faveType.root = new this.fc.TopFavesFolder(faveType.urn); }
// Start watching for the appropriate arc changes
for (var t in faveType.triggers) {
var trig = faveType.triggers[t];
this.ds.removeArcObserver(trig[0], trig[1], trig[2], trig[3], faveType.observer);
}
}
var feedManager = Cc["@flock.com/feed-manager;1"].getService(Ci.flockIFeedManager);
var newsFeedContext = feedManager.getFeedContext("news");
newsFeedContext.removeObserver(this.svc);
}
}
}
this._obsObsrv.fc = this.faves_coop;
this._obsObsrv.svc = this;
this._obsObsrv.ds = this.dataSource;
this._obsObsrv.gtf = gTopFaves;
this._obsObsrv.observe(null, "myworld-enableDisable-observers", "true");
this.obs = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
this.obs.addObserver(this._obsObsrv, "myworld-enableDisable-observers", false);
this.obs.addObserver(this, "flock-shutdown", false);
// set up a prefs observer for the webservice id
var prefBranch2 = PREFS.QueryInterface(Ci.nsIPrefBranch2);
prefBranch2.addObserver(PREF_FIRSTRUN_COMPLETED, this, false);
this.deleteTransients();
this.loaded = true;
this._logger.info("flock favorites data source set up");
}
favoritesService.prototype._shutdown =
function favoritesService__shutdown()
{
for (let [id, timer] in Iterator(this.syncTimers)) {
var sync = timer.callback;
timer.cancel();
sync.notify(null);
}
this.syncTimers = {};
var prefBranch2 = PREFS.QueryInterface(Ci.nsIPrefBranch2);
prefBranch2.removeObserver(PREF_FIRSTRUN_COMPLETED, this);
try {
this.deleteTransients();
}
catch (ex) {
this._logger.debug("ERROR deleting transient data!");
this._logger.debug(ex);
}
this.obs.removeObserver(this._obsObsrv, "myworld-enableDisable-observers");
this.loaded = false;
}
favoritesService.prototype.createBookmarkWithTags =
function (aName, aURL, aShortcutURL, aDescription, aDocCharSet, aPostData, aTags)
{
var bookmark = this.createNewBookmarkWithTags(aName, aURL, aShortcutURL, aDescription,
aDocCharSet, aPostData, aTags);
this.faves_coop.bookmarks_root.children.addOnce(bookmark);
return RDFS.GetResource(bookmark.id())
}
favoritesService.prototype.addBookmarkToFolder =
function (aFolderName, aName, aURL, aShortcutURL, aDescription, aDocCharSet, aPostData, aTags)
{
var folder = this.faves_coop.get(aFolderName);
var bookmark = this.createNewBookmarkWithTags(aName, aURL, aShortcutURL, aDescription,
aDocCharSet, aPostData, aTags);
folder.children.addOnce(bookmark);
return RDFS.GetResource(bookmark.id());
}
favoritesService.prototype.writeBookmarks =
function (aBookmarksFile)
{
var bsvc = Cc["@mozilla.org/browser/bookmarks-service;1"].getService(Ci.flockIBookmarksService);
var dirService = Cc[DIRECTORY_SVC_CONTRACTID].getService(Ci.nsIProperties);
var ds = RDFS.GetDataSource("rdf:flock-favorites").QueryInterface(Ci.nsIRDFDataSource);
var resource = RDF_FOLDERSROOT;
bsvc.WriteBookmarks(aBookmarksFile, ds, resource);
}
favoritesService.prototype.importBookmarks =
function favoritesService_importBookmarks(aBookmarksFile)
{
// Make sure the file exists and is readable
aBookmarksFile.QueryInterface(Ci.nsIFile);
if ((!aBookmarksFile.exists()) || (!aBookmarksFile.isReadable())) {
throw Cr.NS_ERROR_UNEXPECTED;
}
// Load the contents of the file into 'lines' array
var fis = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
fis.init(aBookmarksFile, 1, 0, 0);
fis.QueryInterface(Ci.nsILineInputStream);
var lines = []; var line = {};
while (fis.readLine(line)) { lines.push(line.value); }
// Local functions to import bookmarks and folders
var inst = this;
var decodeEntities = function (str) {
return str.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/&/g, "&")
.replace(/"/g, "\"")
.replace(/'/g, "'");
};
var importBookmark = function () {
var url, lastVisit, lastMod, id, name, desc, feedurl;
if (lines[i].match(/ HREF="([^"]*)"/)) { url = RegExp.$1; }
if (lines[i].match(/ FEEDURL="([^"]*)"/)) { feedurl = RegExp.$1; }
if (lines[i].match(/ LAST_VISIT="([^"]*)"/)) { lastVisit = RegExp.$1; }
if (lines[i].match(/ LAST_MODIFIED="([^"]*)"/)) { lastMod = RegExp.$1; }
if (lines[i].match(/ ID="([^"]*)"/)) { id = RegExp.$1; }
if (lines[i].match(/">(.*)<\/A>/)) { name = decodeEntities(RegExp.$1); }
if (lines[i+1].match(/^ *<DD>(.*)$/)) { desc = decodeEntities(RegExp.$1); i++; }
var bmRes;
if (feedurl) {
bmRes = inst.createLivemark(name, url, feedurl, desc);
}
else if (url == undefined) {
bmRes = inst.createSeparator();
}
else {
bmRes = inst.createBookmarkInternal(name, url, desc, new Date(lastVisit), new Date(lastMod));
}
return inst.faves_coop.get(bmRes.Value);
};
var importFolder = function () {
lines[i++].match(/">(.*)<\/H3/i);
var folderRes = inst.createFolder(RegExp.$1);
var c_folder = inst.faves_coop.get(folderRes.Value);
inst.faves_coop.bookmarks_root.children.remove(c_folder);
if (lines[i].match(/^ *<DD>(.*)$/i)) {
c_folder.description = decodeEntities(RegExp.$1);
i++;
}
if (lines[i].match(/^ *<DL><p>/i)) {
// This folder contains stuff
importContents(c_folder);
}
return c_folder;
};
var importContents = function (aParentFolder) {
i++; // Increment past <DL><p>
while (i < lines.length) {
// inst._logger.warn("\n Parent: "+aParentFolder.Value+" line: "+lines[i]);
var child = null;
if (lines[i].match(/^ *<DT><A /i)) {
child = importBookmark();
} else if (lines[i].match(/^ *<DT><H3/i)) {
child = importFolder();
} else if (lines[i].match(/^ *<\/DL><p>/i)) {
return;
}
if (child) {
aParentFolder.children.addOnce(child);
}
i++;
}
};
// Begin parsing the file
var i = 0;
while ((!lines[i].match(/^ *<DL><p>/i)) && (i < lines.length)) { i++; }
var folder = this.faves_coop.get(this.createFolder("Imported Bookmarks").Value);
importContents(folder);
}
// END flockIFavoritesService
// BEGIN nsIBookmarksService
favoritesService.prototype.addBookmarkImmediately = function (aURI, aTitle, bmType, aDocCharSet)
{
return this.createBookmark(aName, aURI, aURI, "", aDocCharSet, null);
}
favoritesService.prototype.cloneResource = function (aSource)
{
var newResource = RDFS.GetAnonymousResource();
// We need to create CoopType first or the indexer complains
var coopType = this.dataSource.GetTarget(aSource, RDF_COOPTYPE, true);
if (coopType)
this.dataSource.Assert(newResource, RDF_COOPTYPE, coopType, true);
var arcs = this.dataSource.ArcLabelsOut(aSource);
while (arcs.hasMoreElements()) {
var property = arcs.getNext();
property = property.QueryInterface(Ci.nsIRDFResource);
if (property.EqualsNode(this.getBookmarksToolbarFolder())) continue;
if (property.EqualsNode(RDF_COOPTYPE)) continue; // Already created
if (property.EqualsNode(FLRDF('isIndexable'))) continue; // Will be created later
var target = this.dataSource.GetTarget(aSource, property, true);
// Test if the arc points to a child.
if (RDFCU.IsOrdinalProperty(property)) {
var oldChild = target.QueryInterface(Ci.nsIRDFResource);
var newChild = this.cloneResource(oldChild);
this.dataSource.Assert(newResource, property, newChild, true);
} else {
this.dataSource.Assert(newResource, property, target, true);
}
}
// Create isIndexable last to avoid firing the indexer too often
var isIndexable = this.dataSource.GetTarget(aSource, FLRDF('isIndexable'), true);
if (isIndexable)
this.dataSource.Assert(newResource, FLRDF('isIndexable'), isIndexable, true);
return newResource;
}
favoritesService.prototype.createBookmark =
function (aName, aURL, aShortcutURL, aDescription, aDocCharSet, aPostData)
{
if (!aURL || aURL == null) aURL = "about:blank";
var date = new Date();
var bookmark = new this.faves_coop.Bookmark(
{
name: aName,
URL: aURL,
description: aDescription,
BookmarkAddDate: date,
LastVisitDate: date
}
);
return RDFS.GetResource(bookmark.id());
}
favoritesService.prototype.createBookmarkInternal =
function (aName, aURL, aDescription, aLastVisit, aLastMod)
{
if (!aURL || aURL == null) aURL = "about:blank";
var bookmark = new this.faves_coop.Bookmark(
{
name: aName,
URL: aURL,
description: aDescription,
LastVisitDate: aLastVisit,
LastModifiedDate: aLastMod
}
);
return RDFS.GetResource(bookmark.id());
}
favoritesService.prototype.createFolder = function (aName)
{
if (!aName || aName == null) aName = "New Folder";
var folder = new this.faves_coop.Folder({
BookmarkAddDate: new Date(),
name: aName
});
this.faves_coop.bookmarks_root.children.addOnce(folder);
return RDFS.GetResource(folder.id());
}
favoritesService.prototype.createFolderInContainer =
function (aName, aParentFolder, aIndex)
{
var folder = new this.faves_coop.Folder({
BookmarkAddDate: new Date(),
name: aName
});
// default to the favorites_root folder...
var parent = this.faves_coop.favorites_root;
if (aParentFolder) {
// FIXME: get should be able to take an nsIRDFResource as an id
parent = this.faves_coop.get(aParentFolder.ValueUTF8)
}
if (aIndex < 0)
parent.children.add(folder);
else
parent.children.insertAt(folder, aIndex);
return RDFS.GetResource(folder.id());
}
favoritesService.prototype.createLivemark =
function (aName, aURL, aRSSURL, aDescription)
{
var feedService = Cc["@flock.com/feed-manager;1"].getService(Ci.flockIFeedManager);
var livemarkContext = feedService.getFeedContext("livemarks");
var feed = livemarkContext.getRoot().subscribeURL(aRSSURL, aName);
return RDFS.GetResource(feed.id());
}
favoritesService.prototype.createLivemarkInContainer =
function FS_createLivemarkInContainer(aName, aURL, aRSSURL, aDescription, aFolder, aIndex)
{
var feedService = Cc["@flock.com/feed-manager;1"].getService(Ci.flockIFeedManager);
var livemarkContext = feedService.getFeedContext("livemarks");
parent_ = this.faves_coop.get(aFolder.ValueUTF8)
if (!parent_) { // Invalid folder
throw Components.Exception('createLivemarkInContainer: invalid folder '+aFolder.ValueUTF8,
Cr.NS_ERROR_UNEXPECTED);
}
var feed = livemarkContext.getRoot().subscribeURL(aRSSURL, aName);
var coopFeed = this.faves_coop.get(feed.id());
if (aIndex < 0) {
parent_.children.add(coopFeed);
}
else {
parent_.children.insertAt(coopFeed, aIndex);
}
}
favoritesService.prototype.createSeparator = function ()
{
var newSeparator = new this.faves_coop.Separator();
return RDFS.GetResource(newSeparator.id());
}
favoritesService.prototype.getBookmarksToolbarFolder = function ()
{
if (this.faves_coop.toolbar.folder) {
return RDFS.GetResource(this.faves_coop.toolbar.folder.id());
} else {
// JMC - Always have a toolbar folder
var favesToolbar = new this.faves_coop.Folder({name: "Favorites Toolbar"});
this.faves_coop.toolbar.folder = favesToolbar;
this.faves_coop.bookmarks_root.children.addOnce(this.faves_coop.toolbar.folder);
return this.getBookmarksToolbarFolder();
}
}
favoritesService.prototype.getLastCharset = function (aURL) { return null; }
favoritesService.prototype.getParent = function (aSource)
{
if (!aSource || !aSource.QueryInterface || !aSource.QueryInterface(Ci.nsIRDFNode)) return false;
var arcs = this.dataSource.ArcLabelsIn(aSource);
while (arcs && arcs.hasMoreElements()) {
var resource = arcs.getNext();
if (resource && resource.QueryInterface) {
resource = resource.QueryInterface(Ci.nsIRDFResource);
}
if (resource && resource.QueryInterface && RDFCU.IsOrdinalProperty(resource)) {
var parent = this.dataSource.GetSource(resource, aSource, true);
return parent;
}
}
return null;
}
favoritesService.prototype.getParentChain = function (aSource)
{
var chain = [];
var current = this.getParent(aSource);
while (current) {
this._logger.info("parentChain: "+current);
chain.push(current);
current = this.getParent(current);
}
chain.reverse();
return makeNSIArray(chain);
}
favoritesService.prototype.isBookmarked = function (aURL)
{
return this.faves_coop.Bookmark.get_from_url(aURL) != null;
}
favoritesService.prototype.isBookmarkedResource = function (aResource)
{
return this.faves_coop.Bookmark.exists(aResource.Value);
}
favoritesService.prototype.readBookmarks = function () { return; }
favoritesService.prototype.removeBookmarkIcon = function (aURL) { return; }
favoritesService.prototype.resolveKeyword = function (aName, aPostData)
{
var keywordArray = this.faves_coop.Bookmark.find({ShortcutURL: aName})
var keyword = null;
if (keywordArray && keywordArray.length == 1) {
keyword = keywordArray[0].URL;
}
return keyword;
}
favoritesService.prototype.updateBookmarkIcon =
function (aURL, aIconMIMEtype, aIconData, aIconDataLen)
{
var data = "data:";
if (aIconData) {
iconData = String.fromCharCode.apply(null, aIconData);
data += aIconMIMEtype;
data += ";base64,";
data += base64Encode(iconData);
}
var faves = this.faves_coop.Bookmark.find({URL: aURL});
for (var i = 0; i < faves.length; i++) {
var fav = faves[i];
fav.favicon = data;
}
return;
}
favoritesService.prototype.updateLastVisitedDate = function (aURL, docCharset) {
if (aURL == '') return;
var literal = RDFS.GetLiteral(aURL);
var sources = this.dataSource.GetSources(RDF_URL, literal, true);
var bookmark = null;
while (sources && sources.hasMoreElements()) {
var source = sources.getNext().QueryInterface(Ci.nsIRDFResource);
var ctRes = this.dataSource.GetTarget(source, FLRDF("CoopType"), true);
if (ctRes) {
ctRes.QueryInterface(Ci.nsIRDFResource);
if (ctRes.Value == "http://flock.com/rdf#Bookmark") {
bookmark = this.faves_coop.get_from_resource(source);
break;
}
}
}
if (bookmark) {
bookmark.LastVisitDate = new Date();
}
return;
}
//check if string is an integer
favoritesService.prototype.isInt = function (str) {
var i = parseInt (str);
if (isNaN (i))
return false;
i = i . toString ();
if (i != str)
return false;
return true;
}
// END nsIBookmarksService
// BEGIN flockIMigratable
favoritesService.prototype.needsMigration =
function favoritesService_needsMigration(oldVersion)
{
var oldFavoritesFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
oldFavoritesFile.append(OLD_FAVORITES_RDF_FILE);
var relicFavoritesFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
relicFavoritesFile.append(OLD_FAVORITES_RDF_FILE_RELIC);
// only migrate if the old favorites rdf file exists
// FIXME: after the flock_favorites.rdf file is renamed to flock_favorites_old.rdf
// flock_favorites.rdf is created again in the same dir. so we need the 2nd
// condition in the IF to stop migration from happening again
if (oldFavoritesFile.exists() && !relicFavoritesFile.exists()) {
return true;
}
return false;
}
favoritesService.prototype.startMigration =
function (oldVersion, aFlockMigrationProgressListener)
{
// Tell myworld to stop observing.
var obs = getObserverService();
obs.notifyObservers(null, 'myworld-enableDisable-observers', false);
var oldFavoritesFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
oldFavoritesFile.append(OLD_FAVORITES_RDF_FILE);
var ctxt = {
listener: aFlockMigrationProgressListener,
oldFavoritesFile: oldFavoritesFile
};
if (oldFavoritesFile.exists()) {
ctxt.listener.onUpdate(0, 'Migrating favorites');
}
return { wrappedJSObject: ctxt };
}
favoritesService.prototype.doMigrationWork =
function (ctxtWrapper)
{
var ctxt = ctxtWrapper.wrappedJSObject;
if (!ctxt.oldFavoritesFile.exists())
return false;
if (!ctxt.favoritesMigrator)
ctxt.favoritesMigrator = this._migrateFavorites(ctxt);
if (ctxt.favoritesMigrator.next())
ctxt.favoritesMigrator = null;
return Boolean(ctxt.favoritesMigrator);
}
favoritesService.prototype.finishMigration = function (ctxtWrapper) {
// Re-init the topfaves
for (var folderURN in gTopFaves) {
var faveType = gTopFaves[folderURN];
// start gTopFaves init function
faveType.initialize(faveType,this,null);
}
// Tell myworld to resume rdf observation
var obs = getObserverService();
obs.notifyObservers(null, 'myworld-enableDisable-observers', true);
}
// END flockIMigratable
favoritesService.prototype.deleteTransients =
function favoritesService_deleteTransients()
{
this._logger.info(".deleteTransients()");
var types = ["OnlineBookmarksStream", "MediaQuery"];
for (var t in types) {
var type = types[t];
this._logger.info(" deleting transients of type '"+type+"'");
var transientArray = this.faves_coop[type].find({isTransient: true});
for (var i = 0; i < transientArray.length; i++) {
var transient_ = transientArray[i];
this._logger.info('gonna remove transient named ' + transient_.name);
var transientParents = transient_.getParents();
for (var j = 0; j < transientParents.length; j++) {
transientParents[j].children.remove(transient_);
}
if (transient_.children) {
var childEnum = transient_.children.enumerate();
while (childEnum.hasMoreElements()) {
var child = childEnum.getNext();
transient_.children.remove(child);
if (!child.getParent()) child.destroy();
}
}
transient_.destroy();
}
}
// Delete transient accounts
var transientAccounts = this.faves_coop.Account.find({isTransient: true});
for (var j = 0; j < transientAccounts.length; j++) {
var acct = transientAccounts[j];
this._logger.info("Removing transient Account named " + acct.id());
Cc[acct.serviceId].getService(Ci.flockIWebService)
.removeAccount(acct.id());
}
}
favoritesService.prototype.Seq = function (node) {
// make the resource a sequence if its not and return a container object
if (!this.isSeq(node)) {
return RDFCU.MakeSeq(this.dataSource, node);
}
var container = Cc[CONTAINER_CONTRACTID].createInstance(Ci.nsIRDFContainer);
container.Init(this.dataSource, node);
return container;
}
favoritesService.prototype._Seq = favoritesService.prototype.Seq;
favoritesService.prototype.isSeq = function (node) {
// this._logger.info ("Called isSeq with node " + node + "\n");
// is the node a sequence
return RDFCU.IsSeq(this.dataSource, node);
}
favoritesService.prototype.getContainedActions = function (aURL)
{
return simpleEnumerator(this._getContainedActions(aURL, null));
}
favoritesService.prototype._getContainedActions =
function (aURL, aArrIdentityActions)
{
var getIdentityActions = function (aIdentity, identityActions) {
var enabledActions = aIdentity.enabledAction.enumerate();
while (enabledActions.hasMoreElements()) {
var action = enabledActions.getNext();
this._logger.info("adding action " + action.name + " to identityActions ");
identityActions.push({action: action, actionName: action.name, identity: aIdentity});
}
};
if (!aArrIdentityActions) {
aArrIdentityActions = [];
}
var container = this.faves_coop.get(aURL);
if (container instanceof this.faves_coop.Folder) {
// Recurse for each contained Person
var persons = container.children.enumerate();
while (persons.hasMoreElements()) {
this._getContainedActions(aChild.id(), aArrIdentityActions);
}
}
if (container instanceof this.faves_coop.Person) {
var identities = container.children.enumerate();
while (identities.hasMoreElements()) {
var identity = identities.getNext();
getIdentityActions(identity, aArrIdentityActions);
}
}
// return an enumerator of actions?
return aArrIdentityActions;
}
favoritesService.prototype.createSeparatorInContainer =
function (aParentFolder, aIndex)
{
var parentFolder = this.faves_coop.get_from_resource(aParentFolder);
if (parentFolder instanceof this.faves_coop.Stream) throw NS_RDF_ASSERTION_REJECTED;
var newSeparator = new this.faves_coop.Separator();
parentFolder.children.insertAt(newSeparator, aIndex);
return RDFS.GetResource(newSeparator.id());
}
favoritesService.prototype.createNewBookmarkWithTags =
function (aName, aURL, aShortcutURL, aDescription, aDocCharSet, aPostData, aTags)
{
var now = new Date();
if (!aURL || aURL == null) aURL = "about:blank";
var shared = false;
if ( PREFS.getPrefType("flock.bookmarks.shouldnotshare") &&
PREFS.getBoolPref("flock.bookmarks.shouldnotshare") == false )
{
shared = true;
}
return new this.faves_coop.Bookmark(
{
name: aName,
URL: aURL,
description: aDescription,
tags: aTags,
shared: shared,
ShortcutURL: aShortcutURL,
BookmarkAddDate: now,
LastModifiedDate: now,
LastVisitDate: now,
LastCharset: aDocCharSet
}
);
}
favoritesService.prototype.setBookmarksToolbarFolder = function (aSource)
{
var folder = this.faves_coop.get_from_resource(aSource);
if (folder) {
this.faves_coop.toolbar.folder = folder;
}
}
favoritesService.prototype.removeFolder = function (aFolder)
{
// verify the folderness
if (!this.isFolderResource(aFolder)) {
return false;
}
return true;
// FIXME: remove all the children
// FIXME: gc the children as they're removed
// FIXME: remove the name and the type
// FIXME: remove the Seq-ness
// FIXME: remove the folder from it's parent
// FIXME: return success
}
favoritesService.prototype.renameFolder =
function (aFolder, aNewName)
{
// verify the folderness
if (!this.isFolderResource(aFolder)) {
return false;
}
return true;
// FIXME: get the old name...
// FIXME: ds.Change RDF_NAME
// FIXME: return success
}
favoritesService.prototype.moveFolder =
function (aFolder, aNewParent)
{
// verify the folderness
if (!this.isFolderResource(aFolder)) {
return false;
}
var folder = this.faves_coop.get(aFolder.ValueUTF8);
var newparent = this.faves_coop.favorites_root;
if (aNewParent != null) {
newparent = this.faves_coop.get(aNewParent.ValueUTF8);
}
return true;
// FIXME: get old parent folder
// FIXME: remove from old parent folder
// FIXME: add to new parent folder
// FIXME: return success
}
favoritesService.prototype.getFolderName = function (aFolder)
{
// verify the folderness
if (!this.isFolderResource(aFolder)) {
return null;
}
var folder = this.faves_coop.get(aFolder.ValueUTF8);
return folder.name;
}
favoritesService.prototype.createBookmarkInContainer =
function (aName, aURL, aShortcutURL, aDescription, aDocCharSet, aPostData, aFolder, aIndex)
{
var bookmarkResource = this.createBookmark(aName, aURL, aShortcutURL, aDescription, aDocCharSet, aPostData);
var bookmark = this.faves_coop.get(bookmarkResource.Value);
var folder = this.faves_coop.get(aFolder.ValueUTF8);
// FIXME: use index?
folder.children.add(bookmark);
//??? this.removeFavoriteFromFolder(aURL, this.favoritesRoot);
}
favoritesService.prototype.__defineGetter__("migrationName",
function favoritesService_getter_migrationName() {
return "Bookmarks";
});
favoritesService.prototype._migrateFavorites = function (ctxt)
{
// a coop version of the bookmarks_root folder
var realBookmarksRootFolder = this.faves_coop.bookmarks_root.children;
// read into in-memory rdf
var ds = RDFS.GetDataSourceBlocking(IOS.newFileURI(ctxt.oldFavoritesFile).spec);
// coopify the rdf graph
var resourceCount = 0;
var resources = ds.GetAllResources();
// helper function
function _addBookmarkToFolderHelper(aScope, aFolder, aFav) {
aScope.addBookmarkToFolder(aFolder, aFav.Name, aFav.URL, null,
aFav.description, null, null, aFav.tags);
}
while (resources.hasMoreElements()) {
var resource = resources.getNext();
var type_target = ds.GetTarget(resource, RDF_TYPE, true);
if (type_target) {
ds.Assert(resource, RDF_COOPTYPE, type_target, true);
resourceCount++;
}
}
var Coop = loadSubScript("chrome://flock/content/common/coop.js").Coop;
var migration_coop = new Coop(ds, "chrome://flock/content/common/migration-coop.js");
var folderRes;
var favEnum = migration_coop.CardinalFavorite.all();
var favesCount = 0;
var folderID = this.faves_coop.bookmarks_root.id();
while (favEnum.hasMoreElements()) {
var fave = favEnum.getNext();
if (!fave.Name) continue;
if (fave.URL == "http://flock.com/rdf#FavoritesRoot") continue;
var favParents = fave.getParents();
if (favParents) {
// fave.getParents() possibly has an array of null parents. These are
// the bookmarks that are not put into a collection or bookmarks toolbar
// in Cardinal. If there is only 1 entry in array, we need to add
// that bookmark to the bookmarks root.
if (favParents.length == 1 && !favParents[0]) {
_addBookmarkToFolderHelper(this, folderID, fave);
}
}
favesCount++;
var percentage = Math.round(100 * (favesCount / resourceCount));
ctxt.listener.onUpdate(percentage, "Migrating favorites");
yield false;
}
// migrate collections
var collEnum = migration_coop.CardinalCollection.all();
var folderRes = RDFS.GetResource(this.faves_coop.bookmarks_root.id());
while (collEnum.hasMoreElements()) {
var coll = collEnum.getNext();
var folderIndex = -1;
if (!coll) {
// We have to do this since anything that doesn't match the
// migrations-coop schema is returned as null.
continue;
}
if (!coll.Name) {
continue;
}
if (coll.toolbar) {
folderIndex = 1;
}
var folder = this.createFolderInContainer(coll.Name, folderRes, folderIndex);
var collContents = coll.children.enumerate();
while (collContents.hasMoreElements()) {
fave = collContents.getNext();
if (!fave) {
// We have to do this since anything that doesn't match the
// migrations-coop schema is returned as null.
continue;
}
// Add bookmark into new folder from collection in Cardinal.
_addBookmarkToFolderHelper(this, folder.ValueUTF8, fave);
}
if (coll.toolbar) {
// Get the new folder's coop representation.
var newFolder = this.faves_coop.get(folder.ValueUTF8);
// get the bm toolbar folder name from Cormorant
var bmToolbarId = this.getBookmarksToolbarFolder().Value;
var bmToolbarName = this.faves_coop.get(bmToolbarId).name;
// delete the default bookmark toolbar folder
this.faves_coop.get(bmToolbarId).destroy();
this.faves_coop.toolbar.folder = newFolder;
// Change the toolbar folder name to Cormorant's folder name.
this.faves_coop.toolbar.folder.name = bmToolbarName;
}
}
// rename the file and delete the old copy
RDFS.UnregisterDataSource(ds);
ds = null;
migration_coop.datasource = null;
migration_coop = null;
ctxt.oldFavoritesFile.moveTo(null, OLD_FAVORITES_RDF_FILE_RELIC);
yield true;
}
favoritesService.prototype.notifyResolvedCharset =
function FS_notifyResolvedCharset (aCharset, aClosure) {
throw Components.Exception("Unexpected call to NotifyResolvedCharset -- we never set aWantCharset to true!",
Cr.NS_ERROR_UNEXPECTED);
}
favoritesService.prototype.requestCharset =
function FS_requestCharset (aWebNavigation, aChannel, aWantCharset, aClosure) {
aWantCharset.value = false;
aClosure.value = null;
var url = aChannel.URI.spec;
var fav = this.faves_coop.get(url);
if (fav && fav.LastCharset) {
return fav.LastCharset;
} else {
return "";
}
}
// ================================================
// ========== BEGIN XPCOM Module support ==========
// ================================================
function createModule(aParams) {
return {
registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
var aCompMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
aParams.contractID, aFileSpec,
aLocation, aType );
aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
"@mozilla.org/embeddor.implemented/bookmark-charset-resolver;1", aFileSpec,
aLocation, aType );
var catMgr = Cc["@mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
if (!aParams.categories) { aParams.categories = []; }
for (var i = 0; i < aParams.categories.length; i++) {
var cat = aParams.categories[i];
catMgr.addCategoryEntry( cat.category, cat.entry,
cat.value, true, true );
}
},
getClassObject: function (aCompMgr, aCID, aIID) {
if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
return { // Factory
createInstance: function (aOuter, aIID) {
if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
var comp = new aParams.componentClass();
if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
return comp.QueryInterface(aIID);
}
};
},
canUnload: function (aCompMgr) { return true; }
};
}
// NS Module entrypoint
function NSGetModule(aCompMgr, aFileSpec) {
return createModule({
componentClass: favoritesService,
CID: FAVORITES_CID,
contractID: FAVORITES_CONTRACTID,
componentName: "Favorites JS Component",
categories: [
{ category: "flockMigratable", entry: "favorites", value: FAVORITES_CONTRACTID }
]
});
}
// ========== END XPCOM Module support ==========